﻿using Module.NumberGame.Common;
using Prism.Events;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace Module.NumberGame.Views
{
    /// <summary>
    /// Interaction logic for NumberGame
    /// </summary>
    public partial class NumberGameApp : UserControl
    {
        const int TotalRow = 4;
        const int MaxNumber = 10;
        int[,] OldBoardData = new int[TotalRow, TotalRow];
        int[,] NewBoardData = new int[TotalRow, TotalRow];
        bool IsMouseLeftDown;
        bool IsMouseLeftUp;
        double DownX;
        double DownY;
        double OffsetX = 0, OffsetY = 0;
        NumberBox[,] Pieces = new NumberBox[TotalRow, TotalRow];

        private long score;

        private readonly IEventAggregator Ea;
        public NumberGameApp(IEventAggregator ea)
        {
            InitializeComponent();
            this.Ea = ea;
            for (int i = 0; i < TotalRow; i++)
            {
                for (int j = 0; j < TotalRow; j++)
                {
                    Pieces[i, j] = new(i, j, i * (j + 1));

                    GameBoard.Children.Add(Pieces[i, j]);
                }
            }
            ReStart();
        }

        private void PreMouseDown(object sender, MouseButtonEventArgs e)
        {
            IsMouseLeftDown = true;
            IsMouseLeftUp = false;
            DownX = e.GetPosition(this).X;
            DownY = e.GetPosition(this).Y;
        }

        private void PreMouseUp(object sender, MouseButtonEventArgs e)
        {

            if (IsMouseLeftDown && !IsMouseLeftUp && (Math.Abs(OffsetX) > 20 || Math.Abs(OffsetY) > 20))
            {
                for (int i = 0; i < TotalRow; i++)
                    for (int j = 0; j < TotalRow; j++)
                    {
                        OldBoardData[i, j] = NewBoardData[i, j];
                        Pieces[i, j].SetLevel(NewBoardData[i, j]);
                        NewBoardData[i, j] = -1;
                    }
                ProcessPieces(OffsetX, OffsetY);
                for (int i = 0; i < TotalRow; i++)
                    for (int j = 0; j < TotalRow; j++)
                    {
                        Pieces[i, j].SetLevel(NewBoardData[i, j]);
                    }
            }
            IsMouseLeftDown = false;
            IsMouseLeftUp = true;
            OffsetX = 0; OffsetY = 0;

        }

        private void PreMouseMove(object sender, MouseEventArgs e)
        {
            if (IsMouseLeftDown && !IsMouseLeftUp)
            {
                OffsetX = e.GetPosition(this).X - DownX;
                OffsetY = e.GetPosition(this).Y - DownY;
                Ea.GetEvent<NumberMessageEvent>().Publish(new NumberMessage() { MouseDisX = OffsetX, MouseDisY = OffsetY });
            }

        }

        private void ReStartButtonClick(object sender, RoutedEventArgs e)
        {
            ReStart();
        }
        private void ReStart()
        {
            for (int i = 0; i < TotalRow; i++)
                for (int j = 0; j < TotalRow; j++)
                {
                    OldBoardData[i, j] = -1;
                    NewBoardData[i, j] = -1;
                    //if (i is 1 or 2 && j is 1 or 2) { OldBoardData[i, j] = i; NewBoardData[i, j] = i; }
                    Pieces[i, j].SetLevel(NewBoardData[i, j]);
                }
            OldBoardData[0, 0] = 1;
            OldBoardData[1, 1] = 1;
            OldBoardData[2, 2] = 1;
            OldBoardData[3, 3] = 1;
            OldBoardData[3, 0] = 2;
            OldBoardData[2, 1] = 1;
            OldBoardData[1, 2] = 2;
            OldBoardData[0, 3] = 1;
            for (int i = 0; i < TotalRow; i++)
                for (int j = 0; j < TotalRow; j++)
                {
                    NewBoardData[i, j] = OldBoardData[i, j];
                    Pieces[i, j].SetLevel(NewBoardData[i, j]);
                }
            score = 0;
        }
        private void ProcessPieces(double disx, double disy)
        {
            int[,] resl = new int[TotalRow, 2];
            Random randnumber = new();
            int newNum = randnumber.Next(1, MaxNumber);
            int oldtotal = GetNotZeroNumber();

            if (Math.Abs(disx) > Math.Abs(disy)) // 水平移动量大于垂直移动量时，只水平移动
            {
                if (disx < 0) // 向左移动
                {
                    for (int row = 0; row < TotalRow; row++)
                    {
                        resl = Functions.ArrayProcess(OldBoardData[0, row], OldBoardData[1, row], OldBoardData[2, row], OldBoardData[3, row]);
                        NewBoardData[0, row] = resl[0, 0];
                        NewBoardData[1, row] = resl[1, 0];
                        NewBoardData[2, row] = resl[2, 0];
                        NewBoardData[3, row] = resl[3, 0];

                        Pieces[1, row].MoveSteps(resl[1, 1] * -1, 0); // 移动动画
                        Pieces[2, row].MoveSteps(resl[2, 1] * -1, 0); // 移动动画
                        Pieces[3, row].MoveSteps(resl[3, 1] * -1, 0); // 移动动画

                    }
                    if (oldtotal != GetNotZeroNumber()) // 如果数字移动，则增加一个新的数字
                    {
                        Random random = new Random();
                        int index = random.Next(0, 100) % 5;
                        for (int i = 0; i < TotalRow; i++)
                        {
                            if (NewBoardData[4, index] > 0)
                            {
                                index = (index + 1) % 5;
                            }
                            else
                            {
                                NewBoardData[4, index] = newNum;
                                break;
                            }
                        }
                    }
                }
                else // 向右移动
                {
                    for (int row = 0; row < TotalRow; row++)
                    {
                        resl = Functions.ArrayProcess(OldBoardData[3, row], OldBoardData[2, row], OldBoardData[1, row], OldBoardData[0, row]);
                        NewBoardData[3, row] = resl[0, 0];
                        NewBoardData[2, row] = resl[1, 0];
                        NewBoardData[1, row] = resl[2, 0];
                        NewBoardData[0, row] = resl[3, 0];
                        Pieces[2, row].MoveSteps(resl[1, 1], 0); // 移动动画
                        Pieces[1, row].MoveSteps(resl[2, 1], 0); // 移动动画
                        Pieces[0, row].MoveSteps(resl[3, 1], 0); // 移动动画
                    }
                    if (oldtotal != GetNotZeroNumber()) // 如果数字移动，则增加一个新的数字
                    {
                        Random random = new Random();
                        int index = random.Next(0, 100) % 5;
                        for (int i = 0; i < TotalRow; i++)
                        {
                            if (NewBoardData[0, index] > 0)
                            {
                                index = (index + 1) % 5;
                            }
                            else
                            {
                                NewBoardData[0, index] = newNum;
                                break;
                            }
                        }
                    }
                }
            }
            else // 垂直移动
            {
                if (disy < 0) // 向上移动
                {
                    for (int col = 0; col < TotalRow; col++)
                    {
                        resl = Functions.ArrayProcess(OldBoardData[col, 0], OldBoardData[col, 1], OldBoardData[col, 2], OldBoardData[col, 3]);
                        NewBoardData[col, 0] = resl[0, 0];
                        NewBoardData[col, 1] = resl[1, 0];
                        NewBoardData[col, 2] = resl[2, 0];
                        NewBoardData[col, 3] = resl[3, 0];

                        Pieces[col,1].MoveSteps(0, resl[1, 1] * -1); // 移动动画
                        Pieces[col,2].MoveSteps(0, resl[2, 1] * -1); // 移动动画
                        Pieces[col,3].MoveSteps(0, resl[3, 1] * -1); // 移动动画
                    }
                    if (oldtotal != GetNotZeroNumber()) // 如果数字移动，则增加一个新的数字
                    {
                        Random random = new Random();
                        int index = random.Next(0, 100) % 5;
                        for (int i = 0; i < TotalRow; i++)
                        {
                            if (NewBoardData[index, 4] > 0)
                            {
                                index = (index + 1) % 5;
                            }
                            else
                            {
                                NewBoardData[index, 4] = newNum;
                                break;
                            }
                        }
                    }
                }
                else // 向下移动
                {
                    for (int col = 0; col < TotalRow; col++)
                    {
                        resl = Functions.ArrayProcess(OldBoardData[col, 3], OldBoardData[col, 2], OldBoardData[col, 1], OldBoardData[col, 0]);
                        NewBoardData[col, 3] = resl[0, 0];
                        NewBoardData[col, 2] = resl[1, 0];
                        NewBoardData[col, 1] = resl[2, 0];
                        NewBoardData[col, 0] = resl[3, 0];
                        Pieces[col,2].MoveSteps(0, resl[1, 1]); // 移动动画
                        Pieces[col,1].MoveSteps(0, resl[2, 1]); // 移动动画
                        Pieces[col,0].MoveSteps(0, resl[3, 1]); // 移动动画
                    }
                    if (oldtotal != GetNotZeroNumber()) // 如果数字移动，则增加一个新的数字
                    {
                        Random random = new Random();
                        int index = random.Next(0, 100) % 5;
                        for (int i = 0; i < TotalRow; i++)
                        {
                            if (NewBoardData[index, 0] > 0)
                            {
                                index = (index + 1) % 5;
                            }
                            else
                            {
                                NewBoardData[index, 0] = newNum;
                                break;
                            }
                        }
                    }
                }
            }

            score = GetScore();
        }

        

        private int GetScore()
        {
            int score = 0;
            for (int i = 0; i < TotalRow; i++)
            {
                for (int j = 0; j < TotalRow; j++)
                {
                    int num = NewBoardData[i, j];
                    if (num > 2)
                    {
                        score += (int)Math.Pow(3, num);
                    }
                }
            }
            return score;
        }
        private int GetNotZeroNumber() // 获取非零数字的位置，用于判断是否发生了移动。
        {
            return 0;
            int total = 0;
            for (int i = 0; i < TotalRow; i++)
            {
                for (int j = 0; j < TotalRow; j++)
                {
                    if (NewBoardData[i, j] > 0)
                    {
                        total += i + j * 5;
                    }
                }
            }
            return total;
        }
    }
}
